package com.yule.config;

import com.yule.system.dao.*;
import com.yule.system.home.*;
import com.yule.system.model.*;
import com.yule.utils.UserUtils;
import org.apache.commons.lang.builder.ReflectionToStringBuilder;
import org.apache.commons.lang.builder.ToStringStyle;
import org.apache.log4j.Logger;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springside.modules.utils.Collections3;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;

public class MyShiroRealm extends AuthorizingRealm {

    private static final Logger logger = Logger.getLogger(MyShiroRealm.class);

    @Autowired
    private SystemUserHome systemUserHome;

    @Autowired
    private SystemUserRoleHome systemUserRoleHome;

    @Autowired
    private SystemRoleHome systemRoleHome;

    @Autowired
    private SystemRoleMenuHome systemRoleMenuHome;

    @Autowired
    private SystemMenuHome systemMenuHome;

    /**
     * 权限认证（为当前登录的Subject授予角色和权限）
     *
     * 该方法的调用时机为需授权资源被访问时，并且每次访问需授权资源都会执行该方法中的逻辑，这表明本例中并未启用AuthorizationCache，
     * 如果连续访问同一个URL（比如刷新），该方法不会被重复调用，Shiro有一个时间间隔（也就是cache时间，在ehcache-shiro.xml中配置），
     * 超过这个时间间隔再刷新页面，该方法会被执行
     *
     * doGetAuthorizationInfo()是权限控制，
     * 当访问到页面的时候，使用了相应的注解或者shiro标签才会执行此方法否则不会执行，
     * 所以如果只是简单的身份认证没有权限的控制的话，那么这个方法可以不进行实现，直接返回null即可
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        //String loginName = (String) super.getAvailablePrincipal(principalCollection);
        SystemUser user = UserUtils.getUser(super.getAvailablePrincipal(principalCollection));
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        if (user != null) {
            // 权限信息对象info，用来存放查出的用户的所有的角色及权限
            List<SystemRole> systemRoleList = user.getSystemRoleList();
            for (SystemRole systemRole : systemRoleList) {
                //roleList.add(roleInfo.getName());
                info.addRole(systemRole.getName());
            }
            List<SystemMenu> systemMenuList = user.getSystemMenuList();
            for (SystemMenu systemMenu : systemMenuList) {
                info.addStringPermission(systemMenu.getName());
            }
            List<SystemMenu> authMenuList = user.getAuthMenuList();
            for (SystemMenu authMenu : authMenuList) {
                info.addStringPermission(authMenu.getPermissionCode());
            }
        }
        return info;
        // 返回null将会导致用户访问任何被拦截的请求时都会自动跳转到unauthorizedUrl指定的地址
        //return null;
    }

    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        //UsernamePasswordToken用于存放提交的登录信息
        UsernamePasswordToken token = (UsernamePasswordToken)authenticationToken;
        logger.info("登录认证!");
        logger.info("验证当前Subject时获取到token为：" + ReflectionToStringBuilder.toString(token, ToStringStyle.MULTI_LINE_STYLE));
        if (token.getUsername().contains("_")) {
            String dataSource = token.getUsername().split("_")[0];
            DynamicDataSourceContext.setDBType(dataSource);
            SystemUserExample systemUserExample = new SystemUserExample();
            systemUserExample.createCriteria().andUsernameEqualTo(token.getUsername());
            List<SystemUser> userInfoList = systemUserHome.findList(systemUserExample);
            //查询用户信息
            if (userInfoList.size() > 0) {
                SystemUser user = userInfoList.get(0);
                //查询用户角色关联信息
                SystemUserRoleExample systemUserRoleExample = new SystemUserRoleExample();
                systemUserRoleExample.createCriteria().andCorpIdEqualTo(user.getCorpId()).andUserIdEqualTo(user.getId());
                List<SystemUserRole> userRoleList = systemUserRoleHome.findList(systemUserRoleExample);

                if (userRoleList.size() > 0) {
                    //查询用户角色列表
                    SystemRoleExample roleInfoExample = new SystemRoleExample();
                    roleInfoExample.createCriteria().andCorpIdEqualTo(user.getCorpId()).andIdIn(Collections3.extractToList(userRoleList, "roleId"));
                    List<SystemRole> roleInfoList = systemRoleHome.findList(roleInfoExample);
                    user.setSystemRoleList(roleInfoList);

                    //查询角色菜单和角色权限关联
                    SystemRoleMenuExample systemRoleMenuExample = new SystemRoleMenuExample();
                    systemRoleMenuExample.createCriteria().andCorpIdEqualTo(user.getCorpId()).andRoleIdIn(Collections3.extractToList(userRoleList, "roleId"));
                    List<SystemRoleMenu> systemRoleMenuList = systemRoleMenuHome.findList(systemRoleMenuExample);

                    //查询角色菜单和权限
                    DynamicDataSourceContext.setDBType("default");
                    SystemMenuExample systemMenuExample = new SystemMenuExample();
                    systemMenuExample.createCriteria().andIsDelEqualTo(false).andIdIn(Collections3.extractToList(systemRoleMenuList, "menuId"));
                    List<SystemMenu> systemMenuList = systemMenuHome.findList(systemMenuExample);

                    //遍历所有菜单和权限，并根据下级菜单或权限自行添加没有的上级菜单
                    List<SystemMenu> menuList = new LinkedList<SystemMenu>();
                    List<Integer> ids = new ArrayList<Integer>();
                    for (SystemMenu systemMenu : systemMenuList) {
                        //菜单
                        if (systemMenu.getMenuType() == 1) {
                            if (!ids.contains(systemMenu.getPid()) && systemMenu.getPid() !=0) {
                                SystemMenu parentMenu = systemMenuHome.findOne(systemMenu.getPid());
                                menuList.add(parentMenu);
                                ids.add(systemMenu.getPid());
                            }
                            menuList.add(systemMenu);
                            ids.add(systemMenu.getId());
                        } else {
                            //权限
                            if (!ids.contains(systemMenu.getPid())) {
                                SystemMenu parentMenu = systemMenuHome.findOne(systemMenu.getPid());
                                menuList.add(parentMenu);
                                ids.add(systemMenu.getPid());
                                if (!ids.contains(parentMenu.getPid())) {
                                    SystemMenu pMenu = systemMenuHome.findOne(parentMenu.getPid());
                                    menuList.add(pMenu);
                                    ids.add(parentMenu.getPid());
                                }
                            }
                        }
                    }
                    user.setSystemMenuList(menuList);

                    //查询角色权限
                    SystemMenuExample authMenuExample = new SystemMenuExample();
                    authMenuExample.createCriteria().andMenuTypeEqualTo(2).andIsDelEqualTo(false).andIdIn(Collections3.extractToList(systemRoleMenuList, "menuId"));
                    List<SystemMenu> authMenuList = systemMenuHome.findList(authMenuExample);
                    user.setAuthMenuList(authMenuList);
                }

                logger.info("用户: " + user.getUsername());
                // 若存在，将此用户存放到登录认证info中，无需自己做密码对比，Shiro会为我们进行密码对比校验
                return new SimpleAuthenticationInfo(user, user.getPassword(),
                        ByteSource.Util.bytes(user.getSalt()), getName());
            } else {
                return null;
            }
        } else {
            return null;
        }
    }
}
